home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / mnp_c.zip / MNPINTRF.C < prev    next >
C/C++ Source or Header  |  1990-05-16  |  11KB  |  503 lines

  1. /*==========================================================================
  2.  
  3.                        The Microcom MNP Library
  4.                     (Microsoft C Version)
  5.  
  6. ----------------------------------------------------------------------------
  7.  
  8.                 MNPINTRF - MNP Link Interface Routines
  9.  
  10. ----------------------------------------------------------------------------
  11.  
  12.     Modification History
  13.  
  14.     3/30/87 - Compuserve V1.0
  15.  
  16. ==========================================================================*/
  17.  
  18. /* Header files
  19. */
  20. #include <dos.h>
  21. #include <mnpdat.h>
  22.  
  23. /* Local definitions
  24. */
  25. #define NOWAIT        0
  26. #define BIT3SET(bit)        (lcb.status_3 & bit)
  27. #define BIT1SET(bit)        (lcb.status_1 & bit)
  28. #define SETBIT1(bit)        lcb.status_1 |= bit;
  29. #define SETBIT3(bit)        lcb.status_3 |= bit;
  30.  
  31. USIGN_8 get_sbuf();
  32. void mnpdisconnect();
  33. SIGN_16 ia_send();
  34.  
  35. /* Link status block
  36. */
  37. struct link_stat_blk
  38.     {
  39.     USIGN_16 p_status;
  40.     USIGN_16 l_status;
  41.     USIGN_16 s_count;
  42.     USIGN_16 r_count;
  43.     USIGN_16 all_sent;
  44.     };
  45.  
  46. /* External references
  47. */
  48. extern struct BUFFER ftb;
  49. extern struct link_ctl_blk lcb;    /* link control block */
  50. extern struct TIMERS tmr;
  51.  
  52. extern USIGN_16 sf_busy,                /* 'send framer busy' flag */
  53.     sf_lt,                    /* 'LT in progress' flag */
  54.     sf_len,                    /* send framer length */
  55.     tbcnt;                    /* unacked transmit buf count */
  56. extern USIGN_8 chan_no;            /* hardware channel no. */
  57.  
  58. /* Data declarations
  59. */
  60. struct MNP_CB mnpcb;            /* MNP control block */
  61.  
  62. USIGN_8 rbuf[RBUF_LEN];            /* receive buffer */
  63. USIGN_8 *rb_iptr,                /* rcv insert ptr */
  64.     *rb_rptr;                 /* rcv remove ptrs */
  65. USIGN_16 rb_cnt;                /* rcv count */
  66.  
  67. USIGN_8 sbuf[SBUF_LEN];            /* send buffer */
  68. USIGN_8 *sb_iptr,                /* snd insert ptr */
  69.     *sb_rptr;                    /* snd remove ptr */
  70. USIGN_16 sb_cnt;                /* snd count */
  71.  
  72. USIGN_8 *iatbiptr;                /* rcv temp insert ptr */
  73. struct BLST *iatb_struct;        /* transmit buffers */
  74.  
  75. USIGN_8 baudrate;                /* line speed */
  76.  
  77. /*GLOBAL***********************************************************************
  78.  
  79.     mnpconnect - establish an MNP link-connection
  80.  
  81.     synopsis:    retcode = mnpconnect(rate,format,port,mode);
  82.  
  83.     input:    int rate,        physical-connection speed 
  84.                 format,     character format
  85.                 port,        comm port
  86.                 mode;        originator/answerer
  87.  
  88.     output:    int retcode;    establishment result
  89.  
  90. **************************************************************************/
  91.  
  92. SIGN_16 mnpconnect(rate,format,port,mode)
  93.  
  94. USIGN_16 rate,
  95.     format,
  96.     port,
  97.     mode;
  98. {
  99.  
  100. /* Initialize send, receive counts and buffer pointers.
  101. */
  102. rb_cnt = sb_cnt = 0;
  103. rb_iptr = rb_rptr = rbuf;
  104. sb_iptr = sb_rptr = sbuf;
  105.  
  106. /* Initialize physical-connection variables
  107. */
  108. baudrate = rate;
  109. chan_no = port-1;
  110. mnpcb.parity = format;
  111.  
  112. /* Attempt link establishment and exit.  as_connect return code is
  113. ** returned as function value.
  114. */
  115. return(as_connect(&mnpcb,mode));
  116.  
  117. }
  118.  
  119. /*GLOBAL***********************************************************************
  120.  
  121.     mnpdisconnect - terminate an MNP link-connection
  122.  
  123.     synopsis:    mnpdisconnect();
  124.  
  125.     input:    none
  126.  
  127.     output:    none
  128.                ******************************************************************************/
  129. void mnpdisconnect()
  130. {
  131.  
  132. /* Just call mnpllvl routine, signalling link-user initiated termination.
  133. */
  134. as_disconnect(255,0);
  135.  
  136. }
  137.  
  138.  
  139. /*GLOBAL***********************************************************************
  140.  
  141.     mnpreceive - receive data on an MNP link-connection
  142.  
  143.     synopsis:    retcode = mnpreceive(&buffer,buflen);
  144.  
  145.     input:    unsigned char *buffer;    pointer to user buffer
  146.             int buflen;            length of user buffer
  147.  
  148.     output:    int retcode;    if positive, the number of data bytes
  149.                         copied into the user data buffer;
  150.                         if negative, link error code
  151.  
  152. ******************************************************************************/
  153.  
  154. SIGN_16 mnpreceive(bufptr,buflen)
  155.  
  156. USIGN_8 *bufptr;
  157. USIGN_16 buflen;
  158. {
  159.  
  160. SIGN_16 retcode;
  161. register USIGN_16 count;
  162. register USIGN_8 c;
  163.  
  164. /* Maintain the link-connection.  On link error, return with the 
  165. ** error code as the function value.
  166. */
  167. if (retcode = as_link())
  168.     return(retcode);
  169. if (retcode = ia_send(&mnpcb))
  170.     return(retcode);
  171.  
  172. /* Initialize
  173. */
  174. count = 0;
  175.  
  176. /* If there is receive data, copy as much as possible into the
  177. ** user's buffer.  Note that if a 7-bit character format has been
  178. ** selected for the link, then the high-order bit of the data octet
  179. ** is set to 0.
  180. */
  181. while ((rb_cnt > 0) && (buflen > 0))
  182.     {
  183.      buflen--;
  184.      count++;
  185.      rb_cnt--;
  186.      c = *rb_rptr++;
  187.      if (mnpcb.parity) c &= 0x7f;
  188.      *bufptr++ = c;
  189.      if (rb_rptr >= (rbuf + RBUF_LEN))
  190.         rb_rptr = rbuf;
  191.      }
  192.  
  193. /* Maintain the link-connection.  On link error, return with error
  194. ** code as function value.
  195. */
  196. if (retcode = as_link())
  197.     return(retcode);
  198. if (retcode = ia_send(&mnpcb))
  199.     return (retcode);
  200.  
  201. /* Exit.  Function value is the number of octets moved into the user
  202. ** buffer.
  203. */
  204. return(count);
  205. }
  206.  
  207. /*GLOBAL***********************************************************************
  208.  
  209.     mnpsend - send data on an MNP link-connection
  210.  
  211.     synposis:    retcode = mnpsend(&buffer,buflen);
  212.  
  213.     input:    unsigned char *buffer;     pointer to user data buffer
  214.              int buflen;            length of user data buffer
  215.  
  216.     output:   int retcode - if positive, the number of data bytes
  217.                            copied from the user data buffer; 
  218.                              if negative, link error code
  219.  
  220. ***************************************************************************/
  221.  
  222. SIGN_16 mnpsend(bufptr,buflen)
  223.  
  224. USIGN_8 *bufptr;
  225. USIGN_16 buflen;
  226. {
  227.  
  228. SIGN_16 retcode;
  229. register USIGN_16 count;
  230.  
  231. /* Maintain the link-connection.
  232. */
  233. if (retcode = as_link())
  234.     return(retcode);
  235.  
  236. /* Initialize
  237. */
  238. count = 0;
  239.  
  240. /* Copy as much user data as possible into the send ring buffer.
  241. */
  242. while ((sb_cnt < SBUF_LEN) && (buflen > 0))
  243.     {
  244.     count++;
  245.     sb_cnt++;
  246.     buflen--;
  247.     *sb_iptr++ = (unsigned char) setpar(*bufptr++,mnpcb.parity);
  248.     if (sb_iptr >= sbuf + SBUF_LEN)
  249.         sb_iptr = sbuf;
  250.     }
  251.  
  252. /* Try to send an LT LPDU or continue one in progress and maintain
  253. ** the link once again.
  254. */
  255. if (retcode = ia_send(&mnpcb))
  256.     return(retcode);
  257. if (retcode = as_link())
  258.     return(retcode);
  259.  
  260. /* Exit
  261. */
  262. return(count);
  263. }
  264.  
  265. /*GLOBAL***********************************************************************
  266.  
  267.     mnpstatus - get link-connection status information
  268.  
  269.     synopsis:    mnpstatus(&lstat_blk);
  270.  
  271.     input:    struct link_stat_blk *lstat_blk;    pointer to status block
  272.  
  273.     output:    none
  274.  
  275. ******************************************************************************/
  276.  
  277. mnpstatus(lsb)
  278.  
  279. struct link_stat_blk *lsb;
  280. {
  281.  
  282. /* Maintain the link-connection.  Here ignore any link errors as these
  283. ** will be reflected in status values.
  284. */
  285. as_link();
  286. ia_send(&mnpcb);
  287.  
  288. /* Build link status block.
  289. */
  290. if (lne_stat())
  291.     lsb->p_status = FALSE;
  292. else
  293.     lsb->p_status = TRUE;
  294.  
  295. if (BIT1SET(LINK_EST))
  296.     lsb->l_status = TRUE;
  297. else
  298.     lsb->l_status = FALSE;
  299.  
  300. /* Number of bytes free in send buffer. By definition this number is 
  301. ** the size of the send buffer when the link-connection is not 
  302. ** established.
  303. */
  304. if (lsb->l_status == FALSE)
  305.     sb_cnt = 0;
  306. lsb->s_count  = SBUF_LEN - sb_cnt;
  307.  
  308. /* Amount of data in receive buffer
  309. */
  310. lsb->r_count = rb_cnt;
  311.  
  312. /* Data is 'all sent' if the user send buffer is empty and all data
  313. ** messages have been acknowledged.
  314. */
  315. if ((sb_cnt == 0) && (tbcnt == 0))
  316.     lsb->all_sent = TRUE;
  317. else
  318.     lsb->all_sent = FALSE;
  319.  
  320. }
  321.  
  322. /*GLOBAL********************************************************************
  323.  
  324.     mnpbreak - send a break signal (using MNP attention)
  325.  
  326.     synopsis:    retcode = mnpbreak();
  327.  
  328.     input:    none
  329.  
  330.     output:    int retcode;    link error code
  331.  
  332. ***************************************************************************/
  333.  
  334. SIGN_16 mnpbreak()
  335.  
  336. {
  337. SIGN_16 retcode;
  338.  
  339. /* If attention service has not been negotiated for this link-connection,
  340. ** return.  Function value = attention not supported.
  341. */
  342. if (lcb.prot_level != 2)
  343.     return(-75);
  344.  
  345. /* Maintain the link.  Return link error code if link has failed.
  346. */
  347. if (retcode = as_link())
  348.     return(retcode);
  349.  
  350. /* If an attention has already been sent and not yet acknowledged, just
  351. ** return.  Funtion value = attention in progress.  
  352. */
  353. if (BIT3SET(LN_SENT))
  354.     return(-76);
  355.  
  356. /* Ok to send a destructive break using the MNP attention mechanism.
  357. */
  358. clr_int();
  359. rb_iptr = rb_rptr = rbuf;
  360. sb_iptr = sb_rptr = sbuf;
  361. rb_cnt = sb_cnt = NULL;
  362.  
  363. SETBIT3(LN_SENT)
  364.  
  365. link_reset();
  366. dphase_init();
  367.  
  368. SETBIT3(LN_TIMER)
  369. tmr.ln = lcb.lt_tmr;
  370.  
  371. ++lcb.ln_ssn;
  372. lcb.ln_stype=1;
  373. set_int();
  374. return(lpdu_send(LN,NOWAIT));
  375. }
  376.  
  377. /*LOCAL------------------------------------------------------------------------
  378.  
  379.     ia_send - build an LT or add data to one in progress
  380.  
  381. -----------------------------------------------------------------------------*/
  382.  
  383. SIGN_16 ia_send(mnpcb)
  384.  
  385. struct MNP_CB *mnpcb;
  386. {
  387.  
  388. SIGN_16 retcode;
  389.  
  390. /* Just exit if there is nothing to send.
  391. */
  392. if (sb_cnt == 0)
  393.     return(SUCCESS);
  394.  
  395. /* Also just return if an attention is in progress.
  396. */
  397. if (BIT3SET(LN_RECEIVED) || BIT3SET(LN_SENT))
  398.     return(SUCCESS);
  399.  
  400. /* If the send framer is not busy and there is remote credit,
  401. ** start an LT LPDU.
  402. */
  403. clr_int();
  404. if (!sf_busy)
  405.     {
  406.     set_int();
  407.     if (lcb.rem_credit == 0)
  408.         return(SUCCESS);
  409.     if (get_b(mnpcb->ftb, &iatb_struct) == FAILURE)
  410.         return(SUCCESS);
  411.  
  412.     iatb_struct->len = 5;
  413.     iatbiptr = iatb_struct->bptr;
  414.     *iatbiptr++ = 4;
  415.     *iatbiptr++ = LT;
  416.     *iatbiptr++ = 1;
  417.     *iatbiptr++ = 1;
  418.     *iatbiptr++ = ++lcb.lt_ssn;
  419.  
  420. /* Copy bytes out of the send buffer as long as there are any and there
  421. ** is space in the LT LPDU (max is 64 + header of 5 = 69 for Class 3)
  422. */
  423.     while ((iatb_struct->len < 69) && (sb_cnt > 0))
  424.         {
  425.         iatb_struct->len++;
  426.         *iatbiptr++ = get_sbuf();
  427.         }
  428.  
  429. /* Adjust remote credit.
  430. */
  431.     clr_int();
  432.     if (--lcb.rem_credit < 0)
  433.          lcb.rem_credit = 0;
  434.     tbcnt++;
  435.     set_int();
  436.  
  437. /* Now start sending an LT LPDU.  Initiate the LT retransmission timer
  438. ** if it is not already active.
  439. */
  440.     if (retcode = send_pdu(LT, NOWAIT, iatb_struct))
  441.         return(retcode);
  442.     sf_lt = 1;
  443.  
  444.     if (!BIT1SET(RET_TIMER))
  445.         {
  446.         SETBIT1(RET_TIMER)
  447.         tmr.lt = lcb.lt_tmr;
  448.         }
  449.  
  450.     if (ftb.used == 1)
  451.         ftb.used_lst = iatb_struct;
  452.     }
  453.  
  454. /* If the send framer is busy and it is busy with an LT LPDU, try to add
  455. ** as much send buffer data as possible to the current LT.
  456. */
  457. else
  458.     {
  459.     if (sf_lt == 1)
  460.         {
  461.         while ((iatb_struct->len < 69) && (sb_cnt > 0))
  462.             {
  463.             iatb_struct->len++;
  464.             sf_len++;
  465.             *iatbiptr++ = get_sbuf();
  466.             }
  467.         }
  468.     }
  469.  
  470. /* Be sure that interrupts are re-enabled.
  471. */
  472. set_int();
  473.  
  474. /* Exit
  475. */
  476. return(SUCCESS);
  477. }
  478.  
  479. /*LOCAL------------------------------------------------------------------------
  480.  
  481.     get_sbuf - get a data octet from the send buffer
  482.  
  483. -----------------------------------------------------------------------------*/
  484.  
  485. USIGN_8 get_sbuf()
  486. {
  487.  
  488. register USIGN_8 c;
  489.  
  490. /* Remove an octet from the send buffer and return as function value.
  491. ** This routine handles the buffer count and pointer into the circular
  492. ** buffer.
  493. */
  494. sb_cnt--;    
  495. c = *sb_rptr++;
  496. if (sb_rptr >= sbuf + SBUF_LEN)
  497.     sb_rptr = sbuf;
  498.  
  499. /* Exit
  500. */
  501. return(c);
  502. }
  503.